﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using SoftwareConsulting.BI11.Studio.Core.Project.SituationsHierarchy;
using SoftwareConsulting.Interfaces.BasicEntities;
using SoftwareConsulting.BI11.Studio.UI.Properties;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.Studio.UI.ProjectExplorer.SituationsHierarchy
{

    /// <summary>
    /// Класс диалога редактирования описания ситуации
    /// </summary>
    public partial class SituationDescriptionDialog : RestorableForm
	{
        private Situation _situation; //ситуация, у которой редактируем описание
        private ContextMenuStrip _intellisenseWindow; //окно интеллисенса
        private bool _programOpenedIntellisense; //флаг программного раскрытия окна интеллисенса
        private int _lastSelectedIndex; //индекс последней выбранной характеристики
        private int _lastSelectedIndexTableColumn; //индекс последней выбранной табличной колонки       

        /// <summary>
        /// Геттер-сеттер ситуации, у которой редактируем описание
        /// </summary>
        public Situation Situation
        {
            get
            {
                return _situation;
            }
            set
            {
                _situation = value;
            }
        }

        /// <summary>
        /// Инициализация компонентов
        /// </summary>
		public SituationDescriptionDialog(Situation situation)
		{
            Situation = situation;
            InitializeComponent();
            _intellisenseWindow = new ContextMenuStrip();
            _intellisenseWindow.ShowImageMargin = false;
            _intellisenseWindow.Opening+=new CancelEventHandler(_intellisenseWindow_Opening);
            _intellisenseWindow.KeyDown += new KeyEventHandler(_intellisenseListView_KeyDown);            
            _intellisenseWindow.ItemClicked += new ToolStripItemClickedEventHandler(_intellisenseWindow_ItemClicked);
            _programOpenedIntellisense = false;
            _intellisenseWindow.Visible = true;
            PhrasesBox.ContextMenuStrip = _intellisenseWindow;
            _lastSelectedIndex = 0;
            _lastSelectedIndexTableColumn = 0;
		}        

        /// <summary>
        /// Обновление списка фраз в ситуации
        /// </summary>
        private void UpdatePhrases()
        {                        
            Situation.ParsePhrases(PhrasesBox.Lines);
        }

        /// <summary>
        /// Обновление продолжительности события
        /// </summary>
        private void UpdateDuration()
        {
            decimal minutes = Minutes.Value;
            decimal seconds = Seconds.Value;
            Situation.Duration = (double)(minutes + seconds / 60);
        }

        /// <summary>
        /// Обновление информации о событии
        /// </summary>
        private void UpdateEventInfo()
        {
            UpdatePhrases();
            UpdateDuration();
        }

        /// <summary>
        /// Выводит текущую информацию о ситуации
        /// </summary>
        private void RefreshSituationInfo()
        {
            double d = Situation.Duration;
            double mins = Math.Truncate(d);
            Minutes.Value = Math.Round((decimal)(mins));
            Seconds.Value = Math.Round((decimal)((d - mins) * 60));
            List<string> phs = Situation.GetAllPhrasesAsStrings();            
            PhrasesBox.Lines = phs.ToArray();
            Text = Resources.BI_SITUATIONSHIERARCHY_SITUATIONDESCRIPTIONDIALOG_CAPTION + "\"" + Situation.Name + "\"";
        }

        /// <summary>
        /// Отображает окно интеллисенса
        /// </summary>
        private void PrepareIntellisence()
        {            
            //вычищаем старое
            ToolStripItemCollection items = _intellisenseWindow.Items;
            foreach(ToolStripItem tii in items)
            {
                ToolStripMenuItem ti = tii as ToolStripMenuItem;
                if ((ti!=null)&&(ti.DropDown != null)) //ti=null, если это разделитель в меню
                {
                    ti.DropDown.Dispose();
                    ti.DropDown = null;
                }
            }
            items.Clear();
            //добавляем новое
            int sc = _situation.ItemsCount;
            for (int i = 0; i < sc; i++)            
            {                                
                Characteristic ch = _situation.GetItemByPosition(i);
                _intellisenseWindow.Items.Add("%%" + ch.Name);
                ToolStripMenuItem ti = _intellisenseWindow.Items[i] as ToolStripMenuItem;                
                object exp = ch.ExpectedValue;
                if ((ch.IndicatorType == IndicatorType.DateAndFactCorrelations) && (exp != null))
                {
                    /*ContextMenuStrip secondIntellisenceWindow = new ContextMenuStrip();
                    secondIntellisenceWindow.ShowImageMargin = false;
                    secondIntellisenceWindow.KeyDown += new KeyEventHandler(_intellisenceListView_KeyDown);
                    secondIntellisenceWindow.ItemClicked += new ToolStripItemClickedEventHandler(_intellisenceWindow_ItemClicked);
                    IEnumerator en2 = Tables.GetTableByName(mf, exp as string).Columns.GetEnumerator();
                    while (en2.MoveNext())
                    {
                        secondIntellisenceWindow.Items.Add("."+(en2.Current as DataColumn).ColumnName+"%%");
                    }
                    ti.DropDown = secondIntellisenceWindow;                    */
                }
                else
                {
                    ti.Text = ti.Text + "%%";                                        
                }
            }
            _intellisenseWindow.Items.Add("-");
            INamedHierarchy<Characteristic> chs = _situation.GetInternalCharacteristics();
            foreach(Characteristic ch in chs)
            {
                _intellisenseWindow.Items.Add("%%" + ch.Name + "%%");
            }
            ToolStripMenuItem tis = _intellisenseWindow.Items[_lastSelectedIndex] as ToolStripMenuItem;
            if (tis.HasDropDownItems)
            {
                tis.ShowDropDown();                
                tis.DropDown.Items[_lastSelectedIndexTableColumn].Select();                                
            }
            else
            {
                tis.Select();
            }
        }

        /// <summary>
        /// Убирает окно интеллисенса
        /// </summary>
        private void HideIntellisence()
        {
            _intellisenseWindow.Hide();            
            PhrasesBox.Focus();            
        }

        /// <summary>
        /// Выполняет вставку строки из интеллисенса
        /// </summary>
        private void ExecuteIntellisence(ContextMenuStrip contextMenu)
        {
            ToolStripItemCollection items = contextMenu.Items;
            string seltext = "";
            bool failedBecauseTableName = false;
            foreach(ToolStripMenuItem ti in items)            
            {
                if (!string.IsNullOrEmpty(seltext))
                    break;                
                if ((ti != null) && (ti.Selected)) //null - это для разделителя в меню
                {
                    seltext = ti.Text;
                    if (seltext.EndsWith("%%", StringComparison.CurrentCulture))
                    {
                        if (seltext.StartsWith("%%", StringComparison.CurrentCulture))
                        {
                            _lastSelectedIndex = contextMenu.Items.IndexOf(ti);
                        }
                        else
                        {                        
                            ToolStripItem ti2 = contextMenu.OwnerItem;
                            _lastSelectedIndex = ti2.Owner.Items.IndexOf(ti2);
                            _lastSelectedIndexTableColumn=contextMenu.Items.IndexOf(ti);
                            seltext = ti2.Text + seltext;
                        }
                    }
                    else
                    {
                        failedBecauseTableName = true;
                    }
                }
            }
            if (!failedBecauseTableName)
            {
                int index = PhrasesBox.SelectionStart;
                int rowindex = PhrasesBox.GetLineFromCharIndex(index);
                int indexend = PhrasesBox.SelectionStart + PhrasesBox.SelectionLength;
                int rowindexend = PhrasesBox.GetLineFromCharIndex(indexend);
                if (rowindex == rowindexend)
                {
                    int colindex = 0;
                    int colindexend = 0;
                    string s = "";
                    if (PhrasesBox.Lines.Count() > 0)
                    {
                        s = PhrasesBox.Lines[rowindex];
                        colindex = index - PhrasesBox.GetFirstCharIndexFromLine(rowindex);
                        colindexend = indexend - PhrasesBox.GetFirstCharIndexFromLine(rowindexend);
                    }
                    s = s.Substring(0, colindex) + seltext + s.Substring(colindexend);
                    //а далее сплошное извращенство лишь потому
                    //что напрямую сказать Lines[0]="ABC" нельзя
                    //(не срабатывает)
                    string bigs = PhrasesBox.Text;
                    bigs = bigs.Substring(0, PhrasesBox.GetFirstCharIndexFromLine(rowindex)) + s;
                    if (rowindex < (PhrasesBox.Lines.Count() - 1))
                    {
                        bigs = bigs + PhrasesBox.Text.Substring(PhrasesBox.GetFirstCharIndexFromLine(rowindex + 1));
                    }
                    int selneed = PhrasesBox.SelectionStart + seltext.Length;
                    PhrasesBox.Text = bigs;
                    PhrasesBox.SelectionStart = selneed;
                }
                HideIntellisence();
            }
        }

        /// <summary>
        /// Обработка раскрытия контекстного меню
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _intellisenseWindow_Opening(object sender, CancelEventArgs e)
        {
            if (!_programOpenedIntellisense)
            {
                PhrasesBox.SelectionStart = PhrasesBox.GetCharIndexFromPosition(PhrasesBox.PointToClient(new Point(MousePosition.X, MousePosition.Y)));
                PhrasesBox.SelectionLength = 0;
            }
            _programOpenedIntellisense = false;
            PrepareIntellisence();
        }

        /// <summary>
        /// Обработчика клика по пункту интеллисенса
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _intellisenseWindow_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            ExecuteIntellisence(sender as ContextMenuStrip);
        }

        /// <summary>
        /// Обработчик нажатия клавиши внутри окна интеллисенса
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _intellisenseListView_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {                                
                case Keys.Space:                     
                    ExecuteIntellisence(sender as ContextMenuStrip);
                    break;
            }            
        }

        private void OKButton_Click(object sender, EventArgs e)
        {
            UpdateEventInfo();
            Close();
        }

        private void EventDialog_Load(object sender, EventArgs e)
        {
            RefreshSituationInfo();
        }

        private void PhrasesBox_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.KeyCode == Keys.Space) && (e.Modifiers == Keys.Control))
            {                
                Point p = PhrasesBox.GetPositionFromCharIndex(PhrasesBox.SelectionStart);
                p.Offset(0, PhrasesBox.Font.Height);
                _programOpenedIntellisense = true;
                _intellisenseWindow.Show(PhrasesBox, p);
            }            
        }

        private void PhrasesBox_Enter(object sender, EventArgs e)
        {
            if (_intellisenseWindow.Visible)
            {
                HideIntellisence();
            }
        }

	}
}
